﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Xml;
using ControlzEx.Standard;
using LunarSF.SHomeWorkshop.LunarMarkdownEditor.Utils;
using MahApps.Metro.Controls;
using Microsoft.WindowsAPICodePack.Dialogs;
using NPOI.SS.Formula.Functions;
using NPOI.XWPF.UserModel;
using Xceed.Wpf.Toolkit.PropertyGrid.Editors;

namespace LunarSF.SHomeWorkshop.LunarMarkdownEditor
{
    /// <summary>
    /// ImportSubWorkspace.xaml 的交互逻辑
    /// </summary>
    public partial class ImportSubWorkspace : MetroWindow
    {
        public ImportSubWorkspace(WorkspaceTreeViewItem wtvi)
        {
            InitializeComponent();
            baseWtvi = wtvi;

            if (Globals.MainWindow.tvWorkDirectory.Items.Count >= 1 && baseWtvi == Globals.MainWindow.tvWorkDirectory.Items[0])
            {
                tbErrorInfo.Text = "";
                rdImportToSameLevel.IsEnabled = false;
                rdImportToSameLevel.IsChecked = false;
                rdImportToNextLevel.IsEnabled = true;
                rdImportToNextLevel.IsChecked = true;
            }
            else
            {
                switch (baseWtvi.ItemType)
                {
                    case WorkspaceTreeViewItem.Type.File:
                        tbErrorInfo.Text = "";
                        rdImportToNextLevel.IsEnabled = false;
                        rdImportToNextLevel.IsChecked = false;
                        rdImportToSameLevel.IsEnabled = true;
                        rdImportToSameLevel.IsChecked = true;
                        break;
                    case WorkspaceTreeViewItem.Type.Folder:
                        tbErrorInfo.Text = "";
                        rdImportToSameLevel.IsEnabled = true;
                        rdImportToSameLevel.IsChecked = false;
                        rdImportToNextLevel.IsEnabled = true;
                        rdImportToNextLevel.IsChecked = true;
                        break;
                    default:
                        gpCheckImportContents.IsEnabled =
                            gpSelectImportBaseWtvi.IsEnabled =
                            gpSelectSubWorkspacePath.IsEnabled = false;
                        tbErrorInfo.Text = "基准位置错误！";
                        break;
                }
            }
        }

        private WorkspaceTreeViewItem baseWtvi;

        private void btnSelectSubWorkspacePath_Click(object sender, RoutedEventArgs e)
        {
            var dialog = new CommonOpenFileDialog() { Multiselect = false, };
            dialog.IsFolderPicker = true;//设置为选择文件夹
            dialog.Title = Globals.AppName + " - " + "请选择要导入到当前位置的已有工作区目录：";
            if (dialog.ShowDialog() != CommonFileDialogResult.Ok) return;  // 用户取消操作

            if (Directory.Exists(dialog.FileName) == false) return;

            var a = Globals.PathOfWorkspace.ToLower();
            if (a.EndsWith("\\") == false) a += "\\";

            var b = dialog.FileName.ToLower();
            if (b.EndsWith("\\") == false) b += "\\";

            if (b.StartsWith(a))
            {
                LMessageBox.ShowWarning("不能导入当前工作区本身或当前工作区的下级目录！");
                return;
            }

            var wsFilePath = b + "WorkspaceItems.xml";
            if (File.Exists(wsFilePath) == false)
            {
                LMessageBox.ShowWarning("指定目录中不存在工作区目录结构文件。非工作区目录不能导入！");
                return;
            }

            tbxSubWorkspacePath.Text = dialog.FileName;
        }

        private void btnImport_Click(object sender, RoutedEventArgs e)
        {
            var answer = LMessageBox.Show("此操作不可撤销，真的要继续吗？", Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Warning, "", null, this);
            if (answer != MessageBoxResult.Yes)
                return;

            var subWorkspacePath = tbxSubWorkspacePath.Text;
            if (subWorkspacePath.EndsWith("\\") == false)
                subWorkspacePath += "\\";

            if (Directory.Exists(subWorkspacePath) == false)
            {
                LMessageBox.ShowWarning("发生意外，指定要导入的子工作区目录不存在。");
                return;
            }

            var wsFilePath = subWorkspacePath + "WorkspaceItems.xml";
            if (File.Exists(wsFilePath) == false)
            {
                LMessageBox.ShowWarning("指定目录中不存在工作区目录结构文件。非工作区目录不能导入！");
                return;
            }

            // 要解析 WorkspaceItems.xml 文件。
            // 然后递归复制。复制时，要注意路径问题。

            XmlDocument doc = new XmlDocument();
            doc.Load(wsFilePath);

            // 这几项需要递归！
            string result = "";

            //try
            //{
            if (ckxWorkspaceStruct.IsChecked == true)
            {
                var sbErrorInfo = new StringBuilder();

                WorkspaceTreeViewItem newWtvi;

                if (rdImportToNextLevel.IsChecked == true)
                {
                    if (baseWtvi.ItemType != WorkspaceTreeViewItem.Type.Folder)
                    {
                        LMessageBox.ShowWarning("当前选中的节点不是文件夹节点，不能将子工作区导入为下级节点！");
                        return;
                    }

                    newWtvi = BuildNewWorkspaceTreeViewItem(baseWtvi.FullPath + new DirectoryInfo(subWorkspacePath).Name + "\\", doc.DocumentElement);

                    if (Directory.Exists(newWtvi.FullPath))
                    {
                        LMessageBox.ShowWarning($"工作区中指定位置已存在名为【{newWtvi.ShortName}】的文件夹！继续操作可能造成严重数据损失！\r\n\r\n　　如果实在要在这个位置导入，请先在当前工作区中删除该同名文件夹！");
                        return;
                    }

                    bool hasSameTitle = false;

                    foreach (var ti in baseWtvi.Items)
                    {
                        var wi = ti as WorkspaceTreeViewItem;
                        if (wi == null) continue;
                        if (wi.Title.ToLower() == newWtvi.Title.ToLower())
                        {
                            hasSameTitle = true;
                            break;
                        }
                    }

                    if (hasSameTitle)
                    {
                        LMessageBox.ShowWarning($"【{baseWtvi.Title}】的下级节点中已存在标题文本为【{newWtvi.Title}】的文件夹！继续操作可能造成严重数据损失！\r\n\r\n　　如果实在要在这个位置导入，请先在当前工作区中删除已存在的文件夹！");
                        return;
                    }

                    baseWtvi.Items.Add(newWtvi);  // 下级
                }
                else if (rdImportToSameLevel.IsChecked == true)
                {
                    if (baseWtvi.ItemType != WorkspaceTreeViewItem.Type.Folder && baseWtvi.ItemType != WorkspaceTreeViewItem.Type.File)
                    {
                        LMessageBox.ShowWarning("当前选中的节点不是文件夹节点或 Markdown 文件节点，不能将子工作区导入为同级节点！");
                        return;
                    }

                    var parentItem = baseWtvi.ParentWorkspaceTreeViewItem;
                    if (parentItem == null)
                    {
                        LMessageBox.ShowWarning("当前选中的节点没有上级节点，不能将子工作区导入为同级节点！");
                        return;
                    }

                    newWtvi = BuildNewWorkspaceTreeViewItem(parentItem.FullPath + new DirectoryInfo(subWorkspacePath).Name + "\\", doc.DocumentElement);

                    if (Directory.Exists(newWtvi.FullPath))
                    {
                        LMessageBox.ShowWarning($"工作区中指定位置已存在名为【{newWtvi.ShortName}】的文件夹！继续操作可能造成严重数据损失！\r\n\r\n　　如果实在要在这个位置导入，请先在当前工作区中删除该同名文件夹！");
                        return;
                    }

                    bool hasSameTitle = false;

                    foreach (var ti in parentItem.Items)
                    {
                        var wi = ti as WorkspaceTreeViewItem;
                        if (wi == null) continue;
                        if (wi.Title.ToLower() == newWtvi.Title.ToLower())
                        {
                            hasSameTitle = true;
                            break;
                        }
                    }

                    if (hasSameTitle)
                    {
                        LMessageBox.ShowWarning($"已存在与【{baseWtvi.Title}】同级的标题文本为【{newWtvi.Title}】的文件夹！继续操作可能造成严重数据损失！\r\n\r\n　　如果实在要在这个位置导入，请先在当前工作区中删除已存在的文件夹！");
                        return;
                    }

                    parentItem.Items.Add(newWtvi);  // 同级
                }
                else
                {
                    LMessageBox.ShowWarning("没有指定导入位置！");
                    return;
                }

                ImportMarkdownFilesAndResources(newWtvi, newWtvi, doc.DocumentElement, ref sbErrorInfo);
                result += sbErrorInfo;
            }

            // 下面这几个不需要递归！
            result += ImportQuickIcons();
            result += ImportWorkspacePythonScripts();
            result += ImportCustomCssFiles();

            Globals.MainWindow.WorkspaceManager.SaveWorkspaceTreeviewToXml();

            if (string.IsNullOrEmpty(result))
            {
                Globals.MainWindow.LoadWorkspacePythonScriptFiles();
                this.Close();
            }
            else
            {
                LMessageBox.ShowWarning("发生异常，错误消息如下：\r\n\r\n" + result);
            }
            //}
            //catch (Exception ex)
            //{
            //    LMessageBox.ShowWarning(ex.Message);
            //}
        }

        private WorkspaceTreeViewItem BuildNewWorkspaceTreeViewItem(string destDirectoryWtviPath, XmlNode xmlNode)
        {
            if (xmlNode == null) return null;

            WorkspaceTreeViewItem newWtvi;

            var titleAttr = xmlNode.GetAttribute("Title");
            var pathAttr = xmlNode.GetAttribute("Path");
            var statuHeaderAttr = xmlNode.GetAttribute("StatuHeader");
            var statuTailAttr = xmlNode.GetAttribute("StatuTail");
            var tooltipAttr = xmlNode.GetAttribute("Tooltip");
            var isHomePageAttr = xmlNode.GetAttribute("IsHomePage");
            var itemTypeAttr = xmlNode.GetAttribute("ItemType");
            var chmImageIndexAttr = xmlNode.GetAttribute("ChmImageIndex");

            bool isHomePage = false;
            if (isHomePageAttr != null)
            {
                if (bool.TryParse(isHomePageAttr.Value, out bool bHomePage))
                {
                    isHomePage = bHomePage;
                }
            }

            WorkspaceTreeViewItem.Type itype = WorkspaceTreeViewItem.Type.File;
            if (itemTypeAttr != null)
            {
                if (Enum.TryParse(itemTypeAttr.Value, out WorkspaceTreeViewItem.Type t))
                {
                    itype = t;
                }
            }

            int chmIconIndex = 0;
            if (chmImageIndexAttr != null)
            {
                if (int.TryParse(chmImageIndexAttr.Value, out int cii))
                {
                    chmIconIndex = cii;
                }
            }

            var isExpandedAttr = xmlNode.GetAttribute("IsExpanded");

            bool isExpanded = true;
            if (isExpandedAttr != null)
            {
                if (bool.TryParse(isExpandedAttr.Value, out bool ie))
                {
                    isExpanded = ie;
                }
            }

            var subWorkspacePath = tbxSubWorkspacePath.Text;
            if (subWorkspacePath.EndsWith("\\") == false)
                subWorkspacePath += "\\";

            var newPath = ((pathAttr == null || string.IsNullOrEmpty(pathAttr.Value)) ? destDirectoryWtviPath : (destDirectoryWtviPath + pathAttr.Value));

            newWtvi = new WorkspaceTreeViewItem(
                title: (titleAttr == null ? "" : titleAttr.Value),
                path: newPath,
                statusHeader: (statuHeaderAttr == null ? "" : statuHeaderAttr.Value),
                statusTail: (statuTailAttr == null ? "" : statuTailAttr.Value),
                tooltip: (tooltipAttr == null ? "" : tooltipAttr.Value),
                isHomePage: isHomePage,
                itemType: itype,
                chmImageIndex: chmIconIndex,
                isChecked: false,
                Globals.MainWindow);

            newWtvi.IsExpanded = isExpanded;
            return newWtvi;
        }

        private string ImportCustomCssFiles()
        {
            if (ckxWorkspaceCSSStyles.IsChecked == true)
            {
                var subWorkspacePath = tbxSubWorkspacePath.Text;
                if (subWorkspacePath.EndsWith("\\") == false)
                    subWorkspacePath += "\\";

                foreach (var fi in new DirectoryInfo(subWorkspacePath).GetFiles("custom_*.css"))
                {
                    var destCssFilePath = Globals.PathOfWorkspace + fi.Name;
                    if (File.Exists(destCssFilePath))
                    {
                        File.Delete(destCssFilePath);
                    }

                    File.Copy(fi.FullName, destCssFilePath, true);
                }
            }
            return "";
        }

        private string ImportWorkspacePythonScripts()
        {
            if (ckxWorkspacePythonScripts.IsChecked == true)
            {
                var subWorkspacePath = tbxSubWorkspacePath.Text;
                if (subWorkspacePath.EndsWith("\\") == false)
                    subWorkspacePath += "\\";

                var srcPythonScriptDirectoryPath = subWorkspacePath + "_PythonScripts~\\";
                LDirectory.CopyDirectory(srcPythonScriptDirectoryPath, Globals.PathOfWorkspace + "_PythonScripts~\\", false);
            }
            return "";
        }

        private string ImportQuickIcons()
        {
            if (ckxQuickIcons.IsChecked == true)
            {
                var subWorkspacePath = tbxSubWorkspacePath.Text;
                if (subWorkspacePath.EndsWith("\\") == false)
                    subWorkspacePath += "\\";

                var srcQuickIconDirectoryPath = subWorkspacePath + "Images~\\";
                LDirectory.CopyDirectory(srcQuickIconDirectoryPath, Globals.PathOfWorkspace + "Images~\\", false);
            }
            return "";
        }

        private void ImportMarkdownFilesAndResources(WorkspaceTreeViewItem destSubWorkspaceItem, WorkspaceTreeViewItem curWtvi, XmlNode xmlNode, ref StringBuilder sbErrorInfo)
        {
            if (curWtvi == null) return;

            bool copyWorkspaceStruct = (ckxWorkspaceStruct.IsChecked == true);
            if (copyWorkspaceStruct == false) return;  // 用户未勾选

            var subWorkspacePath = tbxSubWorkspacePath.Text;
            if (subWorkspacePath.EndsWith("\\") == false)
                subWorkspacePath += "\\";

            bool copyMarkdownFileContent = (ckxMDContent.IsChecked == true);
            bool copyDocumentImages = (ckxDocumentImages.IsChecked == true);
            bool copyDocumentScriptsAndCssStyles = (ckxDocumentScriptsAndCssStyles.IsChecked == true);  // JavaScript filesList

            if (curWtvi.ItemType == WorkspaceTreeViewItem.Type.Folder)
            {
                if (Directory.Exists(curWtvi.FullPath) == false)
                {
                    Directory.CreateDirectory(curWtvi.FullPath);
                }
            }

            string relativePath = "", srcMdFilePath = "", destMdFilePath = "";

            if (copyMarkdownFileContent)
            {
                // 复制子工作区 Markdown 文件内容
                switch (curWtvi.ItemType)
                {
                    case WorkspaceTreeViewItem.Type.File:
                        {
                            var cfPath = curWtvi.FullPath.ToLower();
                            var destBasePath = destSubWorkspaceItem.FullPath.ToLower();
                            relativePath = cfPath.Substring(destBasePath.Length);
                            break;
                        }
                    case WorkspaceTreeViewItem.Type.Folder:
                        {
                            var cfPath = curWtvi.MetaFilePath.ToLower();
                            var destBasePath = destSubWorkspaceItem.FullPath.ToLower();
                            relativePath = cfPath.Substring(destBasePath.Length);
                            break;
                        }
                }

                var shortName = new DirectoryInfo(subWorkspacePath).Name + "\\";
                if (relativePath.StartsWith(shortName))
                {
                    relativePath = relativePath.Substring(shortName.Length);
                }

                srcMdFilePath = subWorkspacePath + relativePath;
                destMdFilePath = destSubWorkspaceItem.FullPath + relativePath;
                var destDir = new FileInfo(destMdFilePath).Directory.FullName;
                if (Directory.Exists(destDir) == false)
                {
                    Directory.CreateDirectory(destDir);
                }

                File.Copy(srcMdFilePath, destMdFilePath, true);
            }
            else
            {
                // 只复制结构，创建空白 Markdown 文件内容
                var isSampleFile = false;
                var isMetaFile = false;
                switch (curWtvi.ItemType)
                {
                    case WorkspaceTreeViewItem.Type.File:
                        {
                            var cfPath = curWtvi.FullPath.ToLower();
                            var destBasePath = destSubWorkspaceItem.FullPath.ToLower();
                            relativePath = cfPath.Substring(destBasePath.Length);
                            break;
                        }
                    case WorkspaceTreeViewItem.Type.Folder:
                        {
                            var cfPath = curWtvi.MetaFilePath.ToLower();
                            var destBasePath = destSubWorkspaceItem.FullPath.ToLower();
                            relativePath = cfPath.Substring(destBasePath.Length);
                            break;
                        }
                }

                var shortName = new DirectoryInfo(subWorkspacePath).Name + "\\";
                if (relativePath.StartsWith(shortName))
                {
                    relativePath = relativePath.Substring(shortName.Length);
                }

                srcMdFilePath = subWorkspacePath + relativePath;
                destMdFilePath = destSubWorkspaceItem.FullPath + relativePath;
                var destDir = new FileInfo(destMdFilePath).Directory.FullName;
                if (Directory.Exists(destDir) == false)
                {
                    Directory.CreateDirectory(destDir);
                }

                string newShortCommentName = curWtvi.ShortName;
                string docTitle = curWtvi.ShortName;
                using (StreamWriter sw = File.CreateText(destMdFilePath))
                {
                    if (isSampleFile)
                    {
                        sw.Write(Properties.Resources.example);
                    }
                    else
                    {
                        docTitle = newShortCommentName.EndsWith(".md") ? newShortCommentName.Substring(0, newShortCommentName.Length - 3) : newShortCommentName;

                        Regex headerNumberRegex = new Regex(@"^[lL]\d{7,}[ 　-]");
                        var matchHeaderNumber = headerNumberRegex.Match(docTitle);
                        if (matchHeaderNumber.Success)
                        {
                            docTitle = docTitle.Substring(matchHeaderNumber.Length);
                        }

                        var commonTemplateText = "";
                        if (File.Exists(Globals.PathOfWorkspaceCommonTemplateFile))
                        {
                            using (StreamReader sr = File.OpenText(Globals.PathOfWorkspaceCommonTemplateFile))
                            {
                                commonTemplateText = sr.ReadToEnd();
                            }
                        }

                        var metaInlineEnviromentSpan = isMetaFile ? Properties.Resources.metaFileInlineEnviromentTextSpan : "";

                        sw.Write($"\r\n%{docTitle}\r\n\r\n；{DateTime.Now.ToString()}\r\n{metaInlineEnviromentSpan}\r\n{commonTemplateText}");
                    }
                }
            }

            foreach (XmlNode subNode in xmlNode.ChildNodes)
            {
                var newSubWtvi = BuildNewWorkspaceTreeViewItem(destSubWorkspaceItem.FullPath, subNode);
                if (newSubWtvi != null)
                {
                    switch (newSubWtvi.ItemType)
                    {
                        case WorkspaceTreeViewItem.Type.File:
                        case WorkspaceTreeViewItem.Type.Folder:
                            {
                                curWtvi.Items.Add(newSubWtvi);
                                ImportMarkdownFilesAndResources(destSubWorkspaceItem, newSubWtvi, subNode, ref sbErrorInfo);

                                if (copyDocumentScriptsAndCssStyles)
                                {
                                    var srcDirectoryInfo = new FileInfo(srcMdFilePath).Directory;
                                    var srcJavaScriptFiles = srcDirectoryInfo.GetFiles();
                                    foreach (var srcJsFilePath in srcJavaScriptFiles)
                                    {
                                        if (srcJsFilePath.FullName.ToLower().EndsWith(".js") || srcJsFilePath.FullName.ToLower().EndsWith(".css"))
                                        {
                                            var rJsPath = srcJsFilePath.FullName.Substring(subWorkspacePath.Length);
                                            var destJsPath = destSubWorkspaceItem.FullPath + srcJsFilePath.Directory.Name + "\\" + rJsPath;

                                            var destDir = new FileInfo(destJsPath).Directory.FullName;
                                            if (Directory.Exists(destDir) == false)
                                            {
                                                Directory.CreateDirectory(destDir);
                                            }

                                            File.Copy(srcJsFilePath.FullName, destJsPath, true);
                                        }
                                    }
                                }
                                break;
                            }
                        case WorkspaceTreeViewItem.Type.ImageFolder:
                            {
                                if (copyDocumentImages == false) continue;

                                var newImageFolderWtvi = BuildNewWorkspaceTreeViewItem(destSubWorkspaceItem.FullPath, subNode);
                                curWtvi.Items.Insert(0, newImageFolderWtvi);
                                foreach (XmlNode subsubNode in subNode.ChildNodes)
                                {
                                    var imageWtvi = BuildNewWorkspaceTreeViewItem(destSubWorkspaceItem.FullPath, subsubNode);
                                    newImageFolderWtvi.Items.Add(imageWtvi);
                                    var destImagePath = imageWtvi.FullPath;
                                    var rPath = destImagePath.Substring(destSubWorkspaceItem.FullPath.Length);
                                    var shortName = new DirectoryInfo(subWorkspacePath).Name + "\\";
                                    string srcImagePath = "";
                                    if (rPath.StartsWith(shortName))
                                    {
                                        srcImagePath = subWorkspacePath + rPath.Substring(shortName.Length);
                                    }
                                    else
                                    {
                                        srcImagePath = subWorkspacePath + rPath;
                                    }

                                    var destDir = new FileInfo(destImagePath).Directory.FullName;
                                    if (Directory.Exists(destDir) == false)
                                    {
                                        Directory.CreateDirectory(destDir);
                                    }

                                    File.Copy(srcImagePath, destImagePath, false);
                                }
                                break;
                            }
                    }
                }
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            this.Close();
        }

        private void ckxWorkspaceStruct_Unchecked(object sender, RoutedEventArgs e)
        {
            ckxDocumentImages.IsChecked = false;
            ckxDocumentImages.IsEnabled = false;

            ckxDocumentScriptsAndCssStyles.IsChecked = false;
            ckxDocumentScriptsAndCssStyles.IsEnabled = false;

            ckxMDContent.IsChecked = false;
            ckxMDContent.IsEnabled = false;
        }

        private void ckxWorkspaceStruct_Checked(object sender, RoutedEventArgs e)
        {
            ckxDocumentImages.IsChecked = true;
            ckxDocumentImages.IsEnabled = true;

            ckxDocumentScriptsAndCssStyles.IsChecked = true;
            ckxDocumentScriptsAndCssStyles.IsEnabled = true;

            ckxMDContent.IsChecked = true;
            ckxMDContent.IsEnabled = true;
        }

        private void ckxWorkspaceCSSStyles_Click(object sender, RoutedEventArgs e)
        {
            if (ckxWorkspaceCSSStyles.IsChecked == true)
            {
                var answer = LMessageBox.Show(
                "警告！！！\r\n\r\n　　选择导入子工作区自定义样式表会覆盖当前工作区中自定义样式表，且不能撤销。如果不确定请勿勾选此项。\r\n\r\n　　真的要继续吗？",
                Globals.AppName, MessageBoxButton.YesNo, MessageBoxImage.Warning);

                if (answer != MessageBoxResult.Yes)
                    ckxWorkspaceCSSStyles.IsChecked = false;
            }
        }
    }
}
